#!/usr/bin/python
# -*- coding:utf-8 -*-

import os
import sys
import json
import pyDes
import base64
import requests
from requests import Request, Session
from binascii import b2a_hex, a2b_hex
from requests.packages.urllib3.exceptions import InsecureRequestWarning

requests.packages.urllib3.disable_warnings(InsecureRequestWarning)  # 禁用安全请求警告

g_des_key = '1EFDEB7504007654D6D41D35B6E0C0181EFDEB7504007654'  # 初始化des key
g_sid = ''  # session id
g_gray = ''  #
g_urid = ''  # user id
g_city_code = '110000'  # '310000'  # 城市代码


encryptedTk = '05A98230D20F30CC74441032EA25BB2CB97FC034757D2F8FC5FB8222EFC2165E0C3D4517FD21DF5664E741CF74FC118950DFC9775420D10887A1457B75970BB57CBF20B30606AAE8B1E054D6D346A30FA3610F801F068903972D15B0F946E729436FB16C38610D6779D98DB64590C7201B2294F63DD606D1C826FBA375A93749C85CF1EBF4C5E67CD2BE1B0BA4651875B0E7ED54A16D8C086993248D9284338A8DC59EE12DB3460C1718EE031586ACAA73949C03EB8DBBFE0FE868439FAF986CFC20B8777D37F7A927C6A3B247FFF35026E19DF52A635E0A106A81E16EC162DB04503115F93BC3A6D292BAC1D88DDE0D36E60E5C89C8DB24C530EDF188B727C2'
osName = 'ios'
clientVersion = '59'
currentKeyNo = '2'
encryptedVid = '95E714CE3755E2916F238B2514024E766CEBF7A862E81D81'
maxKeyNo = '3'


# 打印函数
def print_hex(data):
    i = 0
    s = ''
    for ch in data:
        ch_i = ord(ch)
        s += '%02x ' % ch_i
        i += 1
        if i % 16 == 0:
            print s
            s = ''
    print s


# 将输入转为utf8格式
def byteify(input, encoding='utf-8'):
    if isinstance(input, dict):
        return {byteify(key): byteify(value) for key, value in input.iteritems()}
    elif isinstance(input, list):
        return [byteify(element) for element in input]
    elif isinstance(input, unicode):
        return input.encode(encoding)
    else:
        return input


# 全局配置设置
def set_config(key='', sid='', gray='', urid='', city_code=''):
    global g_des_key
    global g_sid
    global g_gray
    global g_urid
    global g_city_code

    if len(key) > 0:
        g_des_key = key
    if len(sid) > 0:
        g_sid = sid
    if len(gray) > 0:
        g_gray = gray
    if len(urid) > 0:
        g_urid = urid
    if len(city_code) > 0:
        g_city_code = city_code


############################## 请求接口相关函数开始 ###################################

# 系统初始化接口,获取加密key和sid
def app_sys_init():
    url = 'https://wallet.95516.com/app/inApp/sys/init'
    headers = {'Connection': 'keep-alive',
               'User-Agent': 'iPhone CHSP',
               'Accept': '*/*',
               'Accept-Language': 'zh-Hans;q=1',
               'Content-Type': 'application/json',
               }
    sys_init_params = get_req_sys_init_params()
    s = requests.session()
    r = s.get(url, headers=headers, params=sys_init_params, verify=False)
    res_json = r.json()
    res_json = byteify(res_json)
    res_params = res_json['params']
    encryptedCk = res_params['encryptedCk']
    encryptedVid = res_params['encryptedVid']
    s_key = des_decrypt(encryptedCk)
    s_sid = res_params['sid']
    s_gray = res_params['gray']
    set_config(key=s_key, sid=s_sid, gray=s_gray)
    s_vid = des_decrypt(encryptedVid)
    s_result = r.text.encode('utf8')
    print '[+] app_sys_init:%s,(%s)' % (res_json['msg'], s_result)


# 发送验证短信
def login_code():
    url = 'https://wallet.95516.com/app/inApp/user/sendLoginCode'
    headers = {'Connection': 'keep-alive',
               'User-Agent': 'iPhone CHSP',
               'Accept': '*/*',
               'Accept-Language': 'zh-Hans;q=1',
               'Content-Type': 'application/json',
               'cityCd': g_city_code,
               'gray': g_gray,
               'sid': g_sid
               }
    s = requests.session()
    login_code_params = get_req_login_code_params()
    resp = s.post(url, headers=headers, data=login_code_params, verify=False)
    res = des_decrypt(resp.text)
    res_json = json.loads(res)
    res_json = byteify(res_json)
    print '[+] login_code:%s,(%s)' % (res_json['msg'], res)
    return res_json


# 验证手机短信
def verify_login_code(verify_code):
    url = 'https://wallet.95516.com/app/inApp/user/verifyLoginCode'
    headers = {'Connection': 'keep-alive',
               'User-Agent': 'iPhone CHSP',
               'Accept': '*/*',
               'Accept-Language': 'zh-Hans;q=1',
               'Content-Type': 'application/json',
               'cityCd': g_city_code,
               'gray': g_gray,
               'sid': g_sid
               }
    s = requests.session()
    verify_login_code_params = get_req_verify_login_code_params(verify_code)
    resp = s.post(url, headers=headers, data=verify_login_code_params, verify=False)
    res = des_decrypt(resp.text)
    res_json = json.loads(res)
    res_json = byteify(res_json)
    print '[+] verify_login_code:%s,(%s)' % (res_json['msg'], res)
    return res_json

# 登录接口,通知系统账号登录
def login(user, password):
    url = 'https://wallet.95516.com/app/inApp/user/login'
    headers = {'Connection': 'keep-alive',
               'User-Agent': 'iPhone CHSP',
               'Accept': '*/*',
               'Accept-Language': 'zh-Hans;q=1',
               'Content-Type': 'application/json',
               'cityCd': g_city_code,
               'gray': g_gray,
               'sid': g_sid
               }
    s = requests.session()
    login_params = get_req_login_params(user, password)
    resp = s.post(url, headers=headers, data=login_params, verify=False)
    res = des_decrypt(resp.text)
    res_json = json.loads(res)
    res_json = byteify(res_json)
    print '[+] login:%s,(%s)' % (res_json['msg'], res)
    return res_json


# 获取用户信息接口
def user_info():
    url = 'https://wallet.95516.com/app/inApp/user/get'
    headers = {'Connection': 'keep-alive',
               'User-Agent': 'iPhone CHSP',
               'Accept': '*/*',
               'Accept-Language': 'zh-Hans;q=1',
               'Content-Type': 'application/json',
               'cityCd': g_city_code,
               'gray': g_gray,
               'sid': g_sid
               }
    s = requests.session()
    resp = s.get(url, headers=headers, verify=False)
    res = des_decrypt(resp.text)
    res_json = json.loads(res)
    res_json = byteify(res_json)
    user_id = res_json['params']['urid']
    set_config(urid=user_id)
    print '[+] user_info:%s,(%s)' % (res_json['msg'], res)
    return res_json


# 收款订单列表接口
def order_list(month, pageSize):
    url = 'https://wallet.95516.com/app/inApp/order/list'
    headers = {'Connection': 'keep-alive',
               'User-Agent': 'iPhone CHSP',
               'Accept': '*/*',
               'Accept-Language': 'zh-Hans;q=1',
               'Content-Type': 'application/json',
               'cityCd': g_city_code,
               'gray': g_gray,
               'sid': g_sid,
               'urid': g_urid
               }
    s = requests.session()
    order_list_params = get_req_order_list_params(month, pageSize)
    resp = s.get(url, headers=headers, params=order_list_params, verify=False)
    res = des_decrypt(resp.text)
    res_json = json.loads(res)
    res_json = byteify(res_json)
    print '[+] order_list:%s,(%s)' % (res_json['msg'], res)
    return res_json


# 收款订单详情接口
def order_detail(orderId):
    url = 'https://wallet.95516.com/app/inApp/order/detail'
    headers = {'Connection': 'keep-alive',
               'User-Agent': 'iPhone CHSP',
               'Accept': '*/*',
               'Accept-Language': 'zh-Hans;q=1',
               'Content-Type': 'application/json',
               'cityCd': g_city_code,
               'gray': g_gray,
               'sid': g_sid,
               'urid': g_urid
               }
    s = requests.session()
    order_detail_params = get_req_order_detail_params(orderId)
    resp = s.post(url, headers=headers, data=order_detail_params, verify=False)
    res = des_decrypt(resp.text)
    res_json = json.loads(res)
    res_json = byteify(res_json)
    print '[+] order_detail:%s,(%s)' % (res_json['msg'], res)
    return res_json


# 收款二维码初始化接口
def p2p_pay_init():
    url = 'https://pay.95516.com/pay-web/restlet/qr/p2pPay/getInitInfo'
    headers = {'Connection': 'keep-alive',
               'User-Agent': 'iPhone CHSP',
               'Accept': '*/*',
               'Accept-Language': 'zh-Hans;q=1',
               'Content-Type': 'application/json',
               'cityCd': g_city_code,
               'gray': g_gray,
               'sid': g_sid,
               'urid': g_urid
               }
    s = requests.session()
    p2p_pay_init_params = get_req_p2p_pay_init_params()
    resp = s.get(url, headers=headers, params=p2p_pay_init_params, verify=False)
    res = des_decrypt(resp.text)
    res_json = json.loads(res)
    res_json = byteify(res_json)
    print '[+] p2p_pay_init:%s,(%s)' % (res_json['msg'], res)
    return res_json


# 收款二维码生成接口
# money: 收款金额,单位分
# comments: 备注
# virtual_card_no: 收款卡虚拟标志号
# 返回中的 [params]-> [certificate] 就是收款链接,该链接生成的二维码即可以用ying行类app扫描支付
def applay_qrcode(money, comments, virtual_card_no):
    url = 'https://pay.95516.com/pay-web/restlet/qr/p2pPay/applyQrCode'
    headers = {'Connection': 'keep-alive',
               'User-Agent': 'iPhone CHSP',
               'Accept': '*/*',
               'Accept-Language': 'zh-Hans;q=1',
               'Content-Type': 'application/json',
               'cityCd': g_city_code,
               'gray': g_gray,
               'sid': g_sid,
               'urid': g_urid
               }
    s = requests.session()
    apply_qrcode_params = get_req_apply_qrcode_params(money, comments, virtual_card_no)
    resp = s.get(url, headers=headers, params=apply_qrcode_params, verify=False)
    res = des_decrypt(resp.text)
    res_json = json.loads(res)
    res_json = byteify(res_json)
    print '[+] applay_qrcode:%s,(%s)' % (res_json['msg'], res)
    return res_json

############################## 请求接口相关函数结束 ###################################

############################## 请求参数相关函数开始 ###################################

# 系统初始化请求参数信息
def get_req_sys_init_params():
    sys_init_params = dict()
    sys_init_params['encryptedTk'] = encryptedTk
    sys_init_params['osName'] = osName
    sys_init_params['clientVersion'] = clientVersion
    sys_init_params['currentKeyNo'] = currentKeyNo
    sys_init_params['encryptedVid'] = encryptedVid
    sys_init_params['maxKeyNo'] = maxKeyNo
    return sys_init_params


# 登录验证码请求参数信息
def get_req_login_code_params():
    login_code_params = dict()
    login_code_params_json = json.dumps(login_code_params)
    s_login_code_params = des_encrypt(login_code_params_json).upper()
    return s_login_code_params


# 验证短信验证码请求参数信息
def get_req_verify_login_code_params(verify_code):
    verify_login_code_params = dict()
    verify_login_code_params['smsCode'] = verify_code
    verify_login_code_params_json = json.dumps(verify_login_code_params)
    s_verify_login_code_params = des_encrypt(verify_login_code_params_json)
    s_verify_login_code_params = s_verify_login_code_params.upper()
    return s_verify_login_code_params


# 登录请求参数信息
def get_req_login_params(name, password):
    login_params = dict()
    login_params['password'] = password
    login_params['loginName'] = name
    login_params['cntryCode'] = '+86'
    login_params['imageId'] = ''
    login_params['imageCode'] = ''
    login_params_json = json.dumps(login_params)
    s_login_params = des_encrypt(login_params_json).upper()
    return s_login_params


# 用户信息请求参数信息
def get_req_user_info_params():
    pass


# 收款初始化请求参数信息,主要是获取绑定卡信息
def get_req_p2p_pay_init_params():
    p2p_pay_init_params = dict()
    p2p_pay_init_params['cityCode'] = des_encrypt(g_city_code).upper()
    return p2p_pay_init_params


# 收款二维码信息请求参数信息
def get_req_apply_qrcode_params(money, comments, virtual_card_no):
    apply_qrcode_params = dict()
    apply_qrcode_params['cityCode'] = des_encrypt(g_city_code).upper()
    apply_qrcode_params['comments'] = des_encrypt(comments).upper()
    apply_qrcode_params['txnAmt'] = des_encrypt(money).upper()
    apply_qrcode_params['virtualCardNo'] = des_encrypt(virtual_card_no).upper()
    return apply_qrcode_params


# 收款订单列表请求参数信息
# month:　最近几月的数据,默认'0'
# pageSize: 手机显示一页的数据条目数量,默认'10'
def get_req_order_list_params(month, pageSize):
    order_list_params = dict()
    order_list_params['month'] = des_encrypt(month).upper()
    order_list_params['pageSize'] = des_encrypt(pageSize).upper()
    order_list_params['currentPage'] = des_encrypt('1').upper()
    order_list_params['orderStatus'] = des_encrypt('0').upper()
    order_list_params['orderType'] = des_encrypt('A30000').upper()
    return order_list_params


# 收款订单详情请求参数信息
def get_req_order_detail_params(orderId):
    order_detail_params = dict()
    order_detail_params['orderId'] = orderId
    order_detail_params['orderType'] = '21'
    order_detail_params['transTp'] = 'simple'
    order_detail_params_json = json.dumps(order_detail_params)
    s_order_detail_params = des_encrypt(order_detail_params_json).upper()
    return s_order_detail_params

############################## 请求参数相关函数结束 ###################################

############################## 加密相关函数开始 ###################################

# 数据填充对齐
def padding_zero(data, is_add=True):
    if is_add:
        length = len(data)
        padding_len = 8 - length % 8
        if padding_len == 8:
            padding_len = 0
        zero_string = b'\x00'
        zero_list = list(zero_string)
        res_list = list(data)
        for i in range(0, padding_len):
            res_list.append(zero_list[0])
        res_string = "".join(res_list)
    else:
        data_list = list(data)
        while True:
            end_char = data_list[-1]
            if end_char == b'\x00':
                data_list.pop()
            else:
                break
        res_string = "".join(data_list)
    return res_string


# 获取加密key
def get_key():
    global g_des_key
    key_bin = g_des_key
    key = a2b_hex(key_bin)
    return key


# 加密
def des_encrypt(data):
    key = get_key()
    text = padding_zero(data, True)
    k = pyDes.triple_des(key, pyDes.ECB, IV=None, pad=None, padmode=pyDes.PAD_NORMAL)
    d = k.encrypt(text)
    return b2a_hex(d)


# 解密
def des_decrypt(data):
    key = get_key()
    k = pyDes.triple_des(key, pyDes.ECB, IV=None, pad=None, padmode=pyDes.PAD_NORMAL)
    data_bin = a2b_hex(data)
    d = k.decrypt(data_bin)
    return padding_zero(d, False)

############################## 加密相关函数结束 ###################################


def main():
    app_sys_init()
    info = login('17757782195', 'Weiwei88')
    resp = info['resp']
    if resp == '00':
        # 用户名和密码正确
        params = info['params']
        needVerify = params['needVerify']
        if needVerify == '1':  # 需要短信验证
            info = login_code()
            if info['resp'] == '00':
                # 进一步验证短信验证码
                verify_code = str(input('请输入短信验证码:'))
                info = verify_login_code(verify_code)
                resp = info['resp']
                if resp == '00':  # 短信验证成功
                    print '[+] 短信验证成功'
                else:
                    print '[-] %s' % info['msg']
                    return
            else:
                # 发送短信失败,可能发送短信次数超过单位时间上限
                msg = info['msg']
                print msg
                return

        user_info()  # 获取用户信息
        info = p2p_pay_init()  # 初始化收款二维码相关
        virtual_card_no = info['params']['cardList'][0]['virtualCardNo']  # 测试获取第一张绑定的卡的标志
        info = applay_qrcode('1', '备注', virtual_card_no)  # 设置一个金额为1分钱的备注二维码收款请求,返回中的certificate是收款链接,转成二维码就可以直接扫码使用
        orderList = order_list('0', '10')
        uporders = orderList['params']['uporders']
        if len(uporders) > 0:  # 判断是否有订单
            orderId = orderList['params']['uporders'][0]['orderId']  # 测试获取第一个订单的详细信息
            order_detail(orderId)  # 获取订单的详细信息
        else:
            print "[+] 没有订单!"
    else:
        msg = info['msg']
        print msg

    return


if __name__ == '__main__':
    main()
